#ifndef STX_ALGORITHM_SWAP_HPP
#define STX_ALGORITHM_SWAP_HPP

#include <stx/algorithm/common.hpp>

#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <string>

#include <stack> // Has swap() in C++11
#include <queue> // Has swap() in C++11
#include <valarray> // Has swap() in C++11

#ifdef STX_CPP11
#include <array>
#include <forward_list>
#include <unordered_set>
#include <unordered_map>
#endif

namespace stx {

template<class T>
inline void
swap(T& t1, T& t2)
{
    T tmp = t1;
    t1 = t2;
    t2 = tmp;
}

template<class T, class Allocator>
inline void
swap(std::vector<T, Allocator>& x1, std::vector<T, Allocator>& x2)
{
    x1.swap(x2);
}

template<class T, class Allocator>
inline void
swap(std::deque<T, Allocator>& x1, std::deque<T, Allocator>& x2)
{
    x1.swap(x2);
}

template<class T, class Allocator>
inline void
swap(std::list<T, Allocator>& x1, std::list<T, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class Compare, class Allocator>
inline void
swap(std::set<Key, Compare, Allocator>& x1, std::set<Key, Compare, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class Compare, class Allocator>
inline void
swap(std::multiset<Key, Compare, Allocator>& x1, std::multiset<Key, Compare, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class T, class Compare, class Allocator>
inline void
swap(std::map<Key, T, Compare, Allocator>& x1, std::map<Key, T, Compare, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class T, class Compare, class Allocator>
inline void
swap(std::multimap<Key, T, Compare, Allocator>& x1, std::multimap<Key, T, Compare, Allocator>& x2)
{
    x1.swap(x2);
}

template<class CharT, class CharTraits, class Allocator>
inline void
swap(
    std::basic_string<CharT, CharTraits, Allocator>& x1,
    std::basic_string<CharT, CharTraits, Allocator>& x2)
{
    x1.swap(x2);
}

#ifdef STX_CPP11

template<class T, class Container>
inline void
swap(std::stack<T, Container>& x1, std::stack<T, Container>& x2)
{
    x1.swap(x2);
}

template<class T, class Container>
inline void
swap(std::queue<T, Container>& x1, std::queue<T, Container>& x2)
{
    x1.swap(x2);
}

template<class T, class Container, Compare>
inline void
swap(
    std::priority_queue<T, Container, Compare>& x1,
    std::priority_queue<T, Container, Compare>& x2)
{
    x1.swap(x2);
}

template<class T>
inline void
swap(std::valarray<T>& x1, std::valarray<T>& x2)
{
    x1.swap(x2);
}

template<class T, size_t N>
inline void
swap(std::array<T, N>& x1, std::array<T, N>& x2>
{
    x1.swap(x2);
}

template<class Key, class Hash, class KeyEqual, class Allocator>
inline void
swap(
    std::unordered_set<Key, Hash, KeyEqual, Allocator>& x1,
    std::unordered_set<Key, Hash, KeyEqual, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class Hash, class KeyEqual, class Allocator>
inline void
swap(
    std::unordered_multiset<Key, Hash, KeyEqual, Allocator>& x1,
    std::unordered_multiset<Key, Hash, KeyEqual, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class T, class Hash, class KeyEqual, class Allocator>
inline void
swap(
    std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& x1,
    std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& x2)
{
    x1.swap(x2);
}

template<class Key, class T, class Hash, class KeyEqual, class Allocator>
inline void
swap(
    std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& x1,
    std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& x2)
{
    x1.swap(x2);
}

#endif

} // namespace stx

#endif // STX_ALGORITHM_SWAP_HPP
